#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/rtc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

/*
 * RTC misc driver实现的ioctl命令包括：
 * 命令			解释
 *
 * RTC_AIE_OFF		关闭alarm中断
 * RTC_AIE_ON		打开alarm中断
 * RTC_PIE_ON		打开周期性中断
 * RTC_PIE_OFF		关闭周期性中断
 * RTC_UIE_ON		打开update类型的中断
 * RTC_UIE_OFF		关闭update类型的中断
 * RTC_ALM_READ		读取alarm的时间
 * RTC_ALM_SET		设定alarm的时间
 * RTC_RD_TIME		读取当前的RTC时间
 * RTC_SET_TIME		设定当前的RTC时间
 * RTC_IRQP_READ		读取当前周期性中断的频率
 * RTC_IRQP_SET			设定当前周期性中断的频率
 */

void print_tm(struct rtc_time tm)
{
	printf("time:%04d-%02d-%02d %02d:%02d:%02d\n"
			, tm.tm_year+1900
			, tm.tm_mon
			, tm.tm_mday
			, tm.tm_hour+8
			, tm.tm_min
			, tm.tm_sec);
}

void read_time(int fd)
{
	printf("%s\n", __FUNCTION__);
	struct rtc_time tm;
	int ret = ioctl(fd, RTC_RD_TIME, &tm);
	if (ret < 0)
	{
		perror("read rtc time error\n");
		return ;
	}
	print_tm(tm);
}

void write_time(int fd)
{
	printf("%s\n", __FUNCTION__);
	struct rtc_time tm;
	tm.tm_year = 2021-1900;
	tm.tm_mon = 5;
	tm.tm_mday = 21;
	tm.tm_hour = 19;
	tm.tm_min = 53;
	tm.tm_sec = 10;

	int ret = ioctl(fd, RTC_SET_TIME, &tm);
	if (ret < 0)
	{
		perror("write rtc time error\n");
		return ;
	}
	print_tm(tm);
}

void read_alarm_time(int fd)
{
	printf("%s\n", __FUNCTION__);
	struct rtc_time tm;
	int ret = ioctl(fd, RTC_ALM_READ, &tm);
	if (ret < 0)
	{
		perror("read rtc alarm time error.");
		return ;
	}
	print_tm(tm);

}

void write_alarm_time(int fd)
{
	printf("%s\n", __FUNCTION__);
	struct rtc_time tm;
	tm.tm_year = 2021-1900;
	tm.tm_mon = 5;
	tm.tm_mday = 21;
	tm.tm_hour = 19;
	tm.tm_min = 55;
	tm.tm_sec = 10;

	int ret = ioctl(fd, RTC_ALM_SET, &tm);
	if (ret < 0)
	{
		perror("write rtc alarm time error.");
		return ;
	}
	print_tm(tm);
}

int main(int argc, char *argv[])
{
	int fd = open("/dev/rtc", O_RDWR);
	if (fd < 0 )
	{
		perror("opend device rtc");
		exit(1);
	}

	read_time(fd);
	write_time(fd);
	read_time(fd);

	read_alarm_time(fd);
	write_alarm_time(fd);
	read_alarm_time(fd);
	close(fd);

	return 0;

}
